using System;
using System.Collections;
using System.Windows.Forms;
using System.Web.Services.Protocols;
using ReportViewer.ReportsWS;
using System.Configuration;
using System.Drawing;

namespace ReportViewer
{
    /// <summary>
    /// 
    /// </summary>
    public partial class Reports
    {
        #region Properties

        private readonly ReportingService objRS = new ReportingService();

        private readonly Stack folderHistory;
        private String currentFolder
        {
            get { return folderHistory.Count == 0 ? "/" : (String)folderHistory.Peek(); }
            set { folderHistory.Push(value); }
        }

        private String previousFolder
        {
            get { return folderHistory.Count == 0 ? "/" : (String)folderHistory.Pop(); }
        }

        private String reportFolderField = "/";
        /// <summary>
        /// The report directory to start the application
        /// </summary>
        public String ReportFolder
        {
            get
            {
                if (reportFolderField == "")
                    reportFolderField = @"\";
                return reportFolderField;
            }
            set { reportFolderField = value; }
        }

        private String reportNameField;
        /// <summary>
        /// The report Name to be loaded
        /// </summary>
        public String ReportName
        {
            get { return reportNameField; }
            set { reportNameField = value; }
        }

        private String reportServerUrlField;
        /// <summary>
        /// URL for the remote server
        /// </summary>
        public String ReportServerUrl
        {
            get { return reportServerUrlField; }
            set { reportServerUrlField = value; }
        }

        #endregion

        /// <summary>
        /// Initalize class
        /// </summary>
        public Reports()
        {
            InitializeComponent();
            objRS.Credentials = System.Net.CredentialCache.DefaultCredentials;
            folderHistory = new Stack();

            //Read the configuration file and set the way the report is displayed
            if (ConfigurationManager.AppSettings["ReportWebReport"] != null)
            {
                Constants.VIEW_WEB_REPORT = Convert.ToBoolean(ConfigurationManager.AppSettings["ReportWebReport"]);
            }

        }

        #region Public Methods

        /// <summary>
        /// Call to start the report viewer
        /// </summary>
        public void DisplayReports()
        {
            PopulateReports(ReportFolder, ReportName);
        }

        #endregion

        #region Private Methods

        private void PopulateReports(String reportDirectory)
        {
            //just display the folder
            PopulateReports(reportDirectory, "");
        }

        /// <summary>
        /// Find a list of all the report available
        /// </summary>
        /// <param name="reportDirectory"></param>
        /// <param name="reportName"></param>
        private void PopulateReports(String reportDirectory, string reportName)
        {
            if (ReportServerUrl == null && ConfigurationManager.AppSettings["ReportServer"] != null)
            {
                ReportServerUrl = ConfigurationManager.AppSettings["ReportServer"];
            }

            if (ReportServerUrl != null)
            {
                //Clear the list first
                lstReports.Items.Clear();

                //check to see if we are at the root level
                if (reportDirectory == ReportFolder || reportDirectory == "" || reportDirectory == "/" || reportDirectory == null)
                {
                    currentFolder = reportDirectory;
                }
                else
                {
                    lstReports.Items.Add("<--");
                }

                objRS.Url = String.Format("{0}ReportService.asmx", ReportServerUrl);

                CatalogItem[] items = objRS.ListChildren(reportDirectory, false);
                for (int cnt = 0; cnt < items.Length; cnt++)
                {
                    if (!items[cnt].Hidden)
                    {
                        lstReports.Items.Add(items[cnt].Name);
                        if (items[cnt].Name == reportName)
                        {
                            //need to open the report
                            ShowReport(reportName);
                            return;
                        }
                    }
                }
                currentFolder = reportDirectory;
            }
            else
            {
                throw new Exception("No Report Server Url has been supplied\r\n\r\nHere is an example to enter in the the appp.config file\r\n\r\n<add key=\"ReportServer\" value=\"http://localhost/ReportServer/\" />");
            }

            //If the form is already loaded you don't need to show it again
            if (!Visible)
            {
                //Now display the list of reports
                ShowDialog();
            }
        }

        private ReportParameter[] FindParametersForReport(CatalogItem[] items, int cnt)
        {
            //Find the Parameters for that report
            string report = items[cnt].Path;
            bool forRendering = false;
            string historyID = null;
            Boolean reportCanBeRendered = true;

            //ParameterValue[] values = null;
            //DataSourceCredentials[] credentials = null;
            ReportParameter[] reportParametersArray;
            //ParameterValue[] reportParameterValues = null;

            try
            {
                reportParametersArray = objRS.GetReportParameters(report, historyID, forRendering, null, null);

                if (reportParametersArray != null)
                {
                    //hash table with dependecies 
                    Hashtable Dependencies = new Hashtable();
                    //we need a dynamic array for storing parameter values 
                    ArrayList reportParameterValues;

                    if (reportParametersArray.Length != 0)
                    {
                        reportParameterValues = new ArrayList();
                        //loop over each parameter and build the array of values 
                        foreach (ReportParameter parameter in reportParametersArray)
                        {
                            ParameterValue value = new ParameterValue();
                            value.Name = parameter.Name;
                            value.Label = parameter.Name;
                            //if the report value is coming from URL or previous submission 
                            //then it is part of the Request 
                            if (parameter.Name != null)
                            {
                                //set the value from URL or submission 
                                value.Value = parameter.Name;
                            }
                            else if (parameter.DefaultValues != null)
                            {
                                //set the value to the one defined inside report 
                                value.Value = parameter.DefaultValues[0];
                            }
                            else
                            {
                                //in this case we dont have a value for this parameter 
                                //we cannot render this report 
                                value.Value = "";
                                reportCanBeRendered = false;
                            }

                            if (value.Value != "")
                            {
                                reportParameterValues.Add(value);
                            }

                            //check if this parameter is dependent of another one 
                            if ((parameter.Dependencies != null))
                            {
                                foreach (string d in parameter.Dependencies)
                                {
                                    //add the parameter as a dependecy if was not already added 
                                    if (!Dependencies.Contains(d))
                                    {
                                        Dependencies.Add(d, null);
                                    }
                                }
                            }
                        }
                        //from: For Each Parameter As ReportParameter In Parameters 


                        //Get the list of parameters this time specifying to render the report (ForRender set to true) 
                        //valid values for these parameters will be populated 
                        // TODO:check out http://www.codeproject.com/sqlrs/SQLRSViewer.asp
                        //reportParametersArray = objRS.GetReportParameters(report, null, true, reportParameterValues.ToArray(typeof(ParameterValue)), null);

                        if (reportCanBeRendered)
                            return reportParametersArray;
                        else
                            return null;
                    }
                }
            }



            catch (SoapException ex)
            {
                MessageBox.Show(ex.Detail.InnerXml, Constants.APPLICATION_NAME);
            }

            return null;

        }

        #endregion

        #region Form Objects

        /// <summary>
        /// Open the report you have selected
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmdSelectReport_Click(object sender, EventArgs e)
        {
            ShowReport(lstReports.SelectedItem.ToString());
        }

        /// <summary>
        /// Display a report, if it has parameters then ask for them first
        /// </summary>
        /// <param name="reportName">The Report Name as definded on the Reporting Server</param>
        private void ShowReport(String reportName)
        {
            if (reportName != null)
            {
                CatalogItem[] items = objRS.ListChildren(currentFolder, false);
                for (int cnt = 0; cnt < items.Length; cnt++)
                {
                    if (true)
                    {
                        if (reportName == items[cnt].Name)
                        {
                            switch (items[cnt].Type)
                            {
                                case ItemTypeEnum.Report:
                                    ReportParameter[] rp = FindParametersForReport(items, cnt);

                                    ReportViewer reportViewer = new ReportViewer();

                                    reportViewer.Report.ServerReport.ReportPath = items[cnt].Path;
                                    //reportViewer.Report.ServerReport.DisplayName = String.Format("{0} - {1}", Constants.APPLICATION_NAME, items[cnt].Name.ToString());
                                    //reportViewer.Report.ServerReport.ReportServerUrl = new System.Uri(reportServerUrl, System.UriKind.Absolute);

                                    if (ConfigurationManager.AppSettings["ReportServer"] != null)
                                    {
                                        reportViewer.Report.ServerReport.ReportServerUrl = new Uri(ConfigurationManager.AppSettings["ReportServer"]);
                                    }
                                    else
                                    {
                                        throw new Exception("No Report Server URL in the configuration file, please add ReportServer to the appSettings");
                                    }

                                    String ReportURL;
                                    if (ConfigurationManager.AppSettings["ReportURL"] != null)
                                    {
                                        ReportURL = String.Format("{0}", ConfigurationManager.AppSettings["ReportURL"]);
                                    }
                                    else
                                    {
                                        throw new Exception("No Report URL in the configuration file, please add ReportURL to the appSettings");
                                    }

                                    String url = String.Format(ReportURL, System.Web.HttpUtility.UrlEncode(items[cnt].Path));

                                    if (rp != null)
                                    {
                                        ReportParameters reportParameters = new ReportParameters();
                                        reportParameters.Title = items[cnt].Name;
                                        reportParameters.Description = items[cnt].Description;
                                        reportParameters.Parameters = rp;
                                        reportParameters.ReportViewer = reportViewer;
                                        reportParameters.ReportURL = new Uri(url);
                                        reportParameters.Show();
                                    }
                                    else
                                    {
                                        reportViewer.Show();

                                        ReportViewerWeb reportViewerWeb = new ReportViewerWeb();
                                        reportViewerWeb.WebBrowser.Url = new Uri(url);
                                        reportViewerWeb.Show();
                                    }

                                    break;

                                case ItemTypeEnum.Folder:
                                    //need to load next folder
                                    PopulateReports(items[cnt].Path);
                                    break;

                                case ItemTypeEnum.DataSource:
                                    MessageBox.Show(String.Format("Sorry you can not open Data Sources from here"), Constants.APPLICATION_NAME);
                                    break;

                                case ItemTypeEnum.LinkedReport:
                                    MessageBox.Show(String.Format("Sorry you can not open Linked Reports from here"), Constants.APPLICATION_NAME);
                                    break;

                                case ItemTypeEnum.Resource:
                                    MessageBox.Show(String.Format("Sorry you can not open Resources from here"), Constants.APPLICATION_NAME);
                                    break;

                                case ItemTypeEnum.Unknown:
                                    MessageBox.Show(String.Format("Sorry this is an unknown type"), Constants.APPLICATION_NAME);
                                    break;

                                default:
                                    throw new ApplicationException(String.Format("Unknown type - {0}", items[cnt].Type));
                            }
                        }
                        else if (reportName == "<--")
                        {
                            String gotoDirectory;
                            gotoDirectory = previousFolder;
                            PopulateReports(gotoDirectory);
                        }
                    }
                }
            }
            else
            {
                MessageBox.Show("Please select a report", Constants.APPLICATION_NAME);
            }
        }



        /// <summary>
        /// A report has been selected so enable to report buttton
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EnableReportButton(object sender, EventArgs e)
        {
            if (lstReports.SelectedIndex >= 0)
                cmdSelectReport.Enabled = true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lstReport_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            cmdSelectReport_Click(sender, e);
        }

        private void lblReportViewerTitle_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            //gets the screens width and height, use simple vars instead of calling
            //the GetBounds method all the time
            int screenWidth = Screen.GetBounds(new Point(0, 0)).Width;
            int screenHeight = Screen.GetBounds(new Point(0, 0)).Height;

            //create a new empty bitmap that will hold a screen shot of the whole screen
            Bitmap screenShot = new Bitmap(screenWidth, screenHeight);

            Graphics gfx = Graphics.FromImage((Image)screenShot);  //attach a Graphics object to the bitmap
            gfx.CopyFromScreen(0, 0, 0, 0, new Size(screenWidth, screenHeight));  //gets sreenshot of screen
            //and draws it into bitmap
            Effect fx = new Effect();   //create a new instance of the specialized form called Effect

            gfx = fx.CreateGraphics();  //replace the gfx instance with a new graphics object from the form

            int x = 0, y = 0, width = screenWidth, height = screenHeight;    //set up mutator vars

            while (width >= 0)    //x and y get larger, width and height get smaller
            {
                //gfx.RotateTransform(1.0f); //also neat !enable the one below!
                gfx.DrawImage((Image)screenShot, x, y, width, height);
                x++;
                y++;
                width -= 2;
                height -= 2;
            }
            while (width <= screenWidth)  //x and y get smaller, width and height get larger
            {
                //gfx.RotateTransform(-1.0f);  //also neat !enable the one above!
                gfx.DrawImage((Image)screenShot, x, y, width, height);
                x--;
                y--;
                width += 2;
                height += 2;
            }
        }

        /// <summary>
        /// Close the form down
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            Close();
        }

        #endregion

    }

    #region Easter

    class Effect : Form
    {
        public Effect()
        {
            this.WindowState = FormWindowState.Maximized;  //*take the whole screen 
            this.BackColor = Color.Black;
            this.FormBorderStyle = FormBorderStyle.None;   //*take the whole screen
            this.TopMost = true;  //make it seem like its actually manipulating the screen itself
            this.Show();
        }
    }

    #endregion

}
